package com.yudaxian.bi.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yudaxian.bi.common.Const;
import com.yudaxian.bi.common.ErrorCode;
import com.yudaxian.bi.exception.BusinessException;
import com.yudaxian.bi.model.dto.user.UserLoginRequest;
import com.yudaxian.bi.model.dto.user.UserRegisterRequest;
import com.yudaxian.bi.model.dto.user.UserUpdatePasswordRequest;
import com.yudaxian.bi.model.dto.user.UserUpdateRequest;
import com.yudaxian.bi.model.entity.User;
import com.yudaxian.bi.model.enums.UserRoleEnum;
import com.yudaxian.bi.model.vo.UserLoginVO;
import com.yudaxian.bi.service.UserService;
import com.yudaxian.bi.mapper.UserMapper;
import com.yudaxian.bi.utils.RedisUtil;
import com.yudaxian.bi.utils.StringTools;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;

/**
* @author yudaxian
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2024-09-16 10:28:21
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Resource
    private RedisUtil redisUtil;

    @Override
    public void register(UserRegisterRequest userRegisterRequest) {
        User dbUser = this.getUserByAccount(userRegisterRequest.getUserAccount());
        if (dbUser != null) {
            throw new BusinessException(ErrorCode.USER_REGISTERED_ERROR);
        }

        String checkCode = (String) redisUtil.get(Const.CHECKCODE_KEY + userRegisterRequest.getCheckCodeKey());
        if (checkCode == null) {
            throw new BusinessException(ErrorCode.CHECK_CODE_EXPIRED_ERROR);
        }
        if (!checkCode.equals(userRegisterRequest.getCheckCode())) {
            throw new BusinessException(ErrorCode.CHECK_CODE_ERROR);
        }

        User user = new User();
        Date curDate = new Date();
        // 默认是普通用户
        user.setUserRole(UserRoleEnum.USER.getCode());
        user.setUserAccount(userRegisterRequest.getUserAccount());
        user.setUserName(userRegisterRequest.getUserName());
        user.setCreateTime(curDate);
        user.setUpdateTime(curDate);
        user.setUserPassword(StringTools.encodePassword(userRegisterRequest.getUserPassword()));

        this.save(user);
    }

    @Override
    public UserLoginVO login(UserLoginRequest userLoginRequest) {
        try {
            User dbAccount = this.getUserByAccount(userLoginRequest.getUserAccount());

            if (dbAccount == null) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            if (!StringTools.encodePassword(userLoginRequest.getUserPassword()).equals(dbAccount.getUserPassword())) {
                throw new BusinessException(ErrorCode.PASSWORD_ERROR);
            }

            String checkCode = (String) redisUtil.get(Const.CHECKCODE_KEY + userLoginRequest.getCheckCodeKey());
            if (checkCode == null) {
                throw new BusinessException(ErrorCode.CHECK_CODE_EXPIRED_ERROR);
            }

            if (!checkCode.equals(userLoginRequest.getCheckCode())) {
                throw new BusinessException(ErrorCode.CHECK_CODE_ERROR);
            }

            StpUtil.login(dbAccount.getId());
            UserLoginVO userLoginVO = new UserLoginVO();
            BeanUtils.copyProperties(dbAccount, userLoginVO);
            userLoginVO.setToken(StpUtil.getTokenValueByLoginId(dbAccount.getId()));
            userLoginVO.setId(dbAccount.getId().toString());
            userLoginVO.setUserRole(UserRoleEnum.getEnumByCode(dbAccount.getUserRole()).getValue());
            userLoginVO.setUserAvatar(dbAccount.getUserAvatar());
            return userLoginVO;
        } finally {
            redisUtil.del(Const.CHECKCODE_KEY + userLoginRequest.getCheckCodeKey());
        }
    }

    @Override
    public void updateUserInfo(UserUpdateRequest updateRequest) {
        // 校验用户是否存在
        User userById = this.getById(updateRequest.getId());
        if (userById == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 校验该account是否已经注册
        User dbAccount = this.getUserByAccount(updateRequest.getUserAccount());
        if (!userById.getUserAccount().equals(updateRequest.getUserAccount()) && dbAccount != null) {
            throw new BusinessException(ErrorCode.USER_REGISTERED_ERROR);
        }

        User user = new User();
        user.setId(updateRequest.getId());
        user.setUserAccount(updateRequest.getUserAccount());
        user.setUserName(updateRequest.getUserName());
        user.setUpdateTime(new Date());

        this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getId, updateRequest.getId()));
    }

    @Override
    public void updatePassword(UserUpdatePasswordRequest updatePassword) {
        // 校验用户是否存在
        User userById = this.getById(updatePassword.getId());
        if (userById == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        // 校验密码是否正确
        if (!StringTools.encodePassword(updatePassword.getOriginPassword()).equals(userById.getUserPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_ERROR);
        }
        if (!updatePassword.getNewPassword().equals(updatePassword.getConfirmPassword())) {
            throw new BusinessException(ErrorCode.PASSWORD_NOT_MATCH_ERROR);
        }
        User user = new User();
        user.setId(updatePassword.getId());
        user.setUserPassword(StringTools.encodePassword(updatePassword.getNewPassword()));
        user.setUpdateTime(new Date());

        this.baseMapper.update(user, new LambdaQueryWrapper<User>().eq(User::getId, updatePassword.getId()));
    }

    public User getUserByAccount(String userAccount) {
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getUserAccount, userAccount);
        return this.baseMapper.selectOne(lambdaQueryWrapper);
    }
}




